Add parallel testnet build+deploy to the release pipeline - #9
Merged
Conversation
gpmayorga
force-pushed
the
claude/testnet-parallel-deployment-7ieajb
branch
from
July 17, 2026 00:40
639a146 to
fbc03f6
Compare
ARR552
approved these changes
Aug 14, 2026
On prereleased events, callers can now opt into a second, testnet-mode build (deploy-testnet: true) that deploys to a standalone testnet Worker via a new 'testnet' environment in deploy-app (direct wrangler deploy --env testnet). The testnet build uploads its own run artifact (<app-name>-testnet-build-<sha>) and attaches its own release bundle (<bundle-prefix>-testnet-bundle<tag>.zip), which also makes testnet rollbacks possible: app-rollback.yml gains a 'testnet' environment that redeploys that bundle. New release-pipeline inputs: deploy-testnet, testnet-build-args (default --mode testnet), testnet-build-env, testnet-url; new output: testnet-url. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QZs3qvSwpTvBZEPSqfXQzQ
gpmayorga
force-pushed
the
claude/testnet-parallel-deployment-7ieajb
branch
from
August 18, 2026 18:00
fbc03f6 to
475ed8c
Compare
ARR552
approved these changes
Aug 19, 2026
Drops the deploy-testnet and testnet-url inputs. A new detect-testnet job parses the caller's wrangler.toml and enables the testnet build+deploy when an [env.testnet] section exists, taking the GitHub deployment URL from that section's custom_domain route. The inputs duplicated a fact wrangler.toml already had to state: an app cannot deploy a testnet Worker without declaring it there, so requiring a second "yes I want testnet" flag in the caller workflow only added a place to drift — and forced every consumer to open a workflow PR to adopt the feature. Deriving it means adopting testnet is a config change in the app repo, and because callers pass no inputs an older main would reject, their PRs no longer have to land after this one. Parsed with tomllib, not grep, so comments, key order and quoting cannot change the answer. A malformed wrangler.toml fails the job loudly rather than reading as "no testnet". actions/deploy-app still greps for the prod Worker name; that predates this and should follow, but it sits on the gated promotion path so it is left alone here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QZs3qvSwpTvBZEPSqfXQzQ
gpmayorga
marked this pull request as ready for review
August 19, 2026 17:45
app-promote-production.yml no longer takes a tag input. A new resolve-tag job looks up GitHub's own "latest release" (GET .../releases/latest, which excludes drafts and prereleases) and every downstream step — the ancestry check, the staged-version lookup, the Slack messages — uses that instead of inputs.tag. The tag a `released` event just staged is GitHub's latest release at that exact moment, by construction: prereleased builds it, and flipping the release out of prerelease (the `released` event) is what fires the Slack notification asking someone to promote in the first place. So deriving it loses no legitimate case, while removing the only place an operator could type an arbitrary tag into this workflow. That capability now only exists in the already-gated app-rollback.yml, which is what it's for. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QZs3qvSwpTvBZEPSqfXQzQ
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QZs3qvSwpTvBZEPSqfXQzQ
Removes design-history asides (the abandoned deploy-testnet/testnet-url inputs), restatements of what the YAML already shows, and justification prose that CLAUDE.md already carries as durable guidance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QZs3qvSwpTvBZEPSqfXQzQ
ARR552
approved these changes
Aug 20, 2026
One name per tier, used for the pipeline input, the wrangler env and the GitHub Environment. The main-merge deploy becomes `nightly` (it tracks main) and the release-tag testnet deploy becomes `demo` (it is the thing you show someone). `--mode testnet` is untouched: that names the chain, not the environment. Only two names still differ from their wrangler env, both because two tiers share one Worker: staging is a version alias on the prod Worker, and PR previews are unpromoted versions of the nightly Worker. That collapses the old four-branch mapping in deploy-app to two special cases. Retires public-demo, which nothing consumes once apps-management moves to the demo leg, and which would otherwise collide with the new wrangler [env.demo]. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QZs3qvSwpTvBZEPSqfXQzQ
manimal1
approved these changes
Aug 20, 2026
The Slack notice, its failure message and the step summary all handed out `gh workflow run promote-production.yml ... -f tag=<TAG>`. That input no longer exists, so gh rejects the call with HTTP 422 — the notification was telling deployers to run a command that cannot work. Drops the input from the command and says in the message that promotion targets GitHub's latest release, so the reader knows to release the tag first rather than passing it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QZs3qvSwpTvBZEPSqfXQzQ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two changes to the release pipeline, plus a naming cleanup that touches every environment.
1. A
demoleg on prerelease. Alongside the mainnet staging deploy,prereleasednow runs a second, testnet-mode build and ships it to a standalone Worker (wrangler deploy --env demo). It is enabled by the caller'swrangler.toml: adetect-demojob parses it and turns the leg on when an[env.demo]section exists, taking the deployment URL from that section'scustom_domainroute. No caller input, so adopting it in an app is a config-only change.tomllib, notgrep, so comments, key order and quoting can't change the answer; malformed TOML fails loudly instead of reading as "no demo".2. Promotion takes no
tag.app-promote-production.ymlresolves GitHub's latest release (excludes drafts and prereleases) and promotes that, so there's nowhere to type an arbitrary tag. Promoting a specific non-latest tag isapp-rollback.yml's job.3. One environment name per tier, used for the pipeline input, the wrangler env and the GitHub Environment:
dev/ GHpreviewpreviewmaindemonightlytestnetdemostagingstagingprodprod--mode testnetis untouched — that names the chain, not the environment. Only two names still differ from their wrangler env, both because two tiers share a Worker:staging→prod(version alias) andpreview→nightly(unpromoted version). That collapses the old four-branch mapping indeploy-appto two special cases.This also retires
public-demo, which nothing consumes once apps-management moves to the demo leg, and which would otherwise collide with the new wrangler[env.demo].Contract changes
demo-build-args(default--mode testnet),demo-build-env. Removed:deploy-public-demo, and promotion'stag.demo-url(replacestestnet-url).app-rollback.yml:environment: demoreplacestestnet; theAUTHORIZED_DEPLOYERSgate covers every target.build-demodeclaresenvironment: demo, asbuilddoes for staging, so a protection rule gates the build and not just the deploy.New "Adding an environment" README section and matching
CLAUDE.mdbullets record the conventions: derive targets from app-owned config, parse withtomllib, and keep one name per tier.The earlier revision of this PR was purely additive; the environment rename is not. The library reads the apps' wrangler env names at runtime, so it breaks in whichever direction lands first — the consumer PRs are currently red for exactly this reason (
No environment found in configuration with name "dev").Merge this PR first, then both consumer PRs straight after. Re-running their checks after this lands turns them green.
Only the dev pipeline is exposed in that window:
[env.prod]is untouched andstaging→prodis unchanged, so staging, promotion and production keep working. Worst case in the gap is a failed preview or nightly deploy in an app repo whose PR hasn't merged yet.Verification
actionlint+yamllint(relaxed, line-length off — same aslib-ci) clean.wrangler.toml(enabled, correct URLs), today's appmainwith no[env.demo](disabled — nothing changes for a consumer until it opts in),[env.demo]with no custom domain (enabled, falls back to wrangler's URL), missing file (disabled), malformed TOML (fails with a clear::error::).with:key cross-checked against this workflow's contract.@main, sodeploy-app's new mapping only takes effect once this lands.Consumers
[env.demo]→ demo.app.centrifuge.iopublic-demo→ demo.manage.centrifuge.ioBoth also need a one-time GitHub Environment rename (
demo→nightly) before their first prerelease; details in those PRs.🤖 Generated with Claude Code
https://claude.ai/code/session_01QZs3qvSwpTvBZEPSqfXQzQ